﻿using DiLe.Mes.Application.Common;
using DiLe.Mes.Application.Common.Equipment;
using DiLe.Mes.Application.Common.Equipment.ViewModel;
using DiLe.Mes.Application.Handler;
using DiLe.Mes.Model.Common;
using DiLe.Mes.Model.Common.Equipment.Entity.Maintenance;
using DiLe.Mes.Model.Common.Equipment.Entity.Manage;
using DiLe.Mes.Model.Common.Equipment.Entity.SparePart;
using DiLe.Mes.Model.Common.Equipment.Relation.SparePart;
using Mapster;

namespace DiLe.Mes.Cloud.Controllers.Equipment.Maintenance {
    /// <summary>
    /// 保养记录
    /// </summary>
    [ApiExplorerSettings(GroupName = ApiCloudGroupConst.EquipmentManage)]
    public class MaintenanceRecordController : ApiBaseController {
        private readonly EquipmentMaintenanceClient _maintenanceClient;
        private readonly EquipmentManageClient _equipmentClient;
        private readonly SparePartManageClient _sparePartManageClient;
        private readonly EquipmentExjosnHandler _handler;
        private readonly SparePartManageClient _manageClient;
        private readonly SystemClient _systemClient;
        /// <summary>
        /// 构造函数
        /// </summary>
        public MaintenanceRecordController(EquipmentMaintenanceClient maintenanceClient,
                                           EquipmentExjosnHandler handler,
                                           SparePartManageClient sparePartManageClient,
                                           EquipmentManageClient equipmentManageClient,
                                           SparePartManageClient manageClient,
                                           SystemClient systemClient) {
            _maintenanceClient = maintenanceClient;
            _handler = handler;
            _sparePartManageClient = sparePartManageClient;
            _equipmentClient = equipmentManageClient;
            _manageClient = manageClient;
            _systemClient = systemClient;
        }
        /// <summary>
        /// 获取保养记录列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetMaintenanceRecordList(MaintenanceRecordQueryParameter parameter) {

            var whereExpression = Expressionable.Create<MaintenanceRecordEntity>();
            if (!parameter.Keyword.IsNullOrEmpty()) {
                whereExpression.Or(p => p.Name.Contains(parameter.Keyword));
            }
            if (parameter.EquipmentId > 0) {
                whereExpression.And(x => x.EquipmentId == parameter.EquipmentId);
            }
            if (parameter.MaintenancePlanId > 0) {
                whereExpression.And(x => x.MaintenancePlanId == parameter.MaintenancePlanId);
            }
            if (parameter.Pagination == null) {
                var res = await _maintenanceClient.GetMaintenanceRecordListAsync(whereExpression.ToExpression());
                await _handler.FillMaintenanceRecordExjosn(res);
                return Success(res);
            } else {
                var res = await _maintenanceClient.GetMaintenanceRecordPageListAsync(whereExpression.ToExpression(), parameter.Pagination);
                var list = await _handler.GetMaintenanceRecordDto(res.Record);
                var data = res.Adapt<PaginationModel<MaintenanceRecordDto>>();
                data.Record = list;
                return Success(data);
            }
        }
        /// <summary>
        /// 获取保养记录
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ApiResult> GetMaintenanceRecord(long id) {
            var dto = new MaintenanceRecordDetailDto();
            var res = await _maintenanceClient.GetMaintenanceRecordAsync(id);
            if (res != null && res.Id > 0) {
                await _handler.FillMaintenanceRecordExjosn(new List<MaintenanceRecordEntity> { res });
                dto.Model = res;
                var projecttemps = await _maintenanceClient.GetMaintenanceRecord2ProjectListByPlanIdAsync(id);
                if (!projecttemps.None()) {
                    dto.ProjectRelations = projecttemps;
                    var ids = projecttemps.Select(x => x.MaintenanceProjectId).Distinct().ToList();
                    dto.ProjectDataList = await _maintenanceClient.GetMaintenanceProjectListAsync(x => ids.Contains(x.Id));
                    await _handler.FillMaintenanceProjectExjosn(dto.ProjectDataList);
                }

                dto.PlanModel = await _maintenanceClient.GetMaintenancePlanAsync(res.MaintenancePlanId);
                await _handler.FillMaintenancePlanExjosn(new List<MaintenancePlanEntity> { dto.PlanModel });
                dto.EquipmentModel = await _equipmentClient.GetEquipmentInfoAsync(res.EquipmentId);
                await _handler.FillEquipmentInfoExjosn(new List<EquipmentInfoEntity> { dto.EquipmentModel });
                if (res.SparePartStockOutId > 0) {
                    dto.SparePartStockOutModel = await GetSparePartStockOut(res.SparePartStockOutId);
                }
            }
            return Success(dto);
        }
        /// <summary>
        /// 获取出库管理
        /// </summary>
        /// <returns></returns>

        private async Task<SparePartStockOutDto> GetSparePartStockOut(long id) {
            var dto = new SparePartStockOutDto();
            var res = await _manageClient.GetSparePartStockOutAsync(id);
            dto.Model = res;
            if (res.Id > 0) {
                var temps = await _manageClient.GetStockOutSparePartListByStockOutIdAsync(id);
                if (!temps.None()) {
                    dto.Relations = temps;
                    var ids = temps.Select(x => x.SparePartId).Distinct().ToList();
                    var dataList = await _manageClient.GetSparePartLedgerListAsync(p => ids.Contains(p.Id));
                    dto.DataList = await _handler.FillSparePartLedgerExjosn(dataList);
                }
            }
            await _handler.FillSparePartStockOutExjosn(new List<SparePartStockOutEntity> { dto.Model });
            return dto;
        }

        /// <summary>
        /// 保存保养记录
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> SaveMaintenanceRecord(MaintenanceRecordSaveParameter parameter) {
            var rp = parameter.MaintenanceRecordParameter;
            if (rp.Model.IsReplace) {
                var stockoutid = await SaveSparePartStockOut(parameter.StockOutParameter);
                rp.Model.SparePartStockOutId = stockoutid;
            }
            var resId = await _maintenanceClient.SaveMaintenanceRecordAsync(rp.Model);
            if (resId > 0) {
                if (!rp.AddRelations.None()) {
                    await _maintenanceClient.InsertMaintenanceRecord2ProjectAsync(resId, rp.AddRelations);
                }
                if (!rp.EidtRelations.None()) {
                    await _maintenanceClient.UpdateMaintenanceRecord2ProjectAsync(rp.EidtRelations);
                }
                if (!rp.DeleteRelations.None()) {
                    await _maintenanceClient.DeleteMaintenanceRecord2ProjectAsync(rp.DeleteRelations);
                }
            }
            return resId > 0 ? Success() : Fail();
        }

        /// <summary>
        /// 保存出库管理
        /// </summary>
        /// <returns></returns>
        private async Task<long> SaveSparePartStockOut(SaveParameter<SparePartStockOutEntity, StockOutSparePartEntity> parameter) {
            var res = await _manageClient.SaveSparePartStockOutAsync(parameter.Model);
            if (res.Id > 0) {
                if (!parameter.AddRelations.None()) {
                    await _manageClient.InsertStockOutSparePartAsync(res.Id, parameter.AddRelations);
                    var maps = parameter.AddRelations.GroupBy(p => p.SparePartId).Select(t => (t.Key, t.Sum(x => x.StockOutNumber))).ToList();
                    foreach (var item in maps) {
                        await MinusSparePartInventory(res.WarehouseId, item.Key, item.Item2);
                    }
                }
                if (!parameter.EidtRelations.None()) {
                    await _manageClient.UpdateStockOutSparePartAsync(parameter.EidtRelations);
                    var ids = parameter.EidtRelations.ConvertAll(x => x.Id);
                    var oldRels = await _manageClient.GetStockOutSparePartList(p => ids.Contains(p.Id));
                    var oldmaps = oldRels.GroupBy(p => p.SparePartId).Select(t => (t.Key, t.Sum(x => x.StockOutNumber))).ToList();
                    foreach (var item in oldmaps) {
                        await MinusSparePartInventory(res.WarehouseId, item.Key, item.Item2);
                    }
                    var maps = parameter.EidtRelations.GroupBy(p => p.SparePartId).Select(t => (t.Key, t.Sum(x => x.StockOutNumber))).ToList();
                    foreach (var item in maps) {
                        await AddSparePartInventory(res.WarehouseId, item.Key, item.Item2);
                    }
                }
                if (!parameter.DeleteRelations.None()) {
                    await _manageClient.DeleteStockOutSparePartAsync(parameter.DeleteRelations);
                    var maps = parameter.AddRelations.GroupBy(p => p.SparePartId).Select(t => (t.Key, t.Sum(x => x.StockOutNumber))).ToList();
                    foreach (var item in maps) {
                        await AddSparePartInventory(res.WarehouseId, item.Key, item.Item2);
                    }
                }
            }
            return res.Id;
        }

        /// <summary>
        /// 删除保养记录
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> DeleteMaintenanceRecord(List<long> ids) {
            var list = await _maintenanceClient.GetMaintenanceRecordListAsync(p => ids.Contains(p.Id));
            var stockoutids = list.Where(x => x.IsReplace).Select(i => i.SparePartStockOutId).ToList();
            if (!stockoutids.None()) {
                await DeleteSparePartStockOut(stockoutids);
            }
            var res = await _maintenanceClient.DeleteMaintenanceRecordAsync(ids);
            return res ? Success() : Fail();
        }
        /// <summary>
        /// 删除出库管理
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        private async Task<bool> DeleteSparePartStockOut(List<long> ids) {
            var rels = await _manageClient.GetStockOutSparePartList(p => ids.Contains(p.StockOutId));
            var dataList = await _manageClient.GetSparePartStockOutListAsync(p => ids.Contains(p.Id));
            foreach (var item in dataList) {
                var maps = rels.Where(p => p.StockOutId == item.Id).GroupBy(p => p.SparePartId).Select(t => (t.Key, t.Sum(x => x.StockOutNumber))).ToList();
                foreach (var map in maps) {
                    await AddSparePartInventory(item.WarehouseId, map.Key, map.Item2);
                }
            }
            var res = await _manageClient.DeleteSparePartStockOutAsync(ids);
            return res;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="warehouseId"></param>
        /// <param name="sparePartId"></param>
        /// <param name="quantity"></param>
        private async Task AddSparePartInventory(long warehouseId, long sparePartId, int quantity) {
            var inventory = await _systemClient.GetSparePartInventoryAsync(p => p.SparePartId == sparePartId && p.WarehouseId == warehouseId);
            if (inventory == null) {
                inventory = new SparePartInventoryEntity() {
                    InventoryQuantity = quantity,
                    SparePartId = sparePartId,
                    WarehouseId = warehouseId
                };
                await _systemClient.InsertSparePartInventoryAsync(inventory);
            } else {
                inventory.InventoryQuantity += quantity;
                await _systemClient.UpdateSparePartInventoryAsync(new List<SparePartInventoryEntity> { inventory });
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="warehouseId"></param>
        /// <param name="sparePartId"></param>
        /// <param name="quantity"></param>
        private async Task MinusSparePartInventory(long warehouseId, long sparePartId, int quantity) {
            var inventory = await _systemClient.GetSparePartInventoryAsync(p => p.SparePartId == sparePartId && p.WarehouseId == warehouseId);
            if (inventory != null) {
                inventory.InventoryQuantity -= quantity;
                await _systemClient.UpdateSparePartInventoryAsync(new List<SparePartInventoryEntity> { inventory });
            }
        }

    }
}
